var OOJ = {};
OOJ.lang = (function () {
	
	var extend = function (subClass, superClass, subPrototype) {
		if (!subClass || !superClass) {
			throw new Error("!");
		}
		var F = function() {};
		F.prototype = superClass.prototype;
		subClass.prototype = new F();
		subClass.prototype.constructor = subClass;
		subClass.superclass = superClass.prototype;
		if (superClass.prototype.constructor == Object.prototype.constructor) {
			superClass.prototype.constructor = superClass;
		}
		
		if (subPrototype) {
			for (var k in subPrototype) {
				subClass.prototype[k] = subPrototype[k];
			}
		}
	}
	
	var isString = function (str) {
		return (typeof str == 'string');
	}
	
	var getById = function (id) {
		if (typeof id == 'string') {
            return document.getElementById(id);
        } else if (typeof id == 'object') {
            return id;
        }
	}
	
	return {
		extend: extend,
		isString: isString,
		getById: getById
	}
	
})();


OOJ.util = (function () {
	
	var L = OOJ.lang;

	var Event = {
		
		/**
		 * @property _listeners
		 * @type Array
		 * @private
		 * @deprecated
		 */
		_listeners: [],
		
		/**
		 * @method addEventListener
		 * @param {string} el
		 * @param {string} eType
		 * @param {Function} handler
		 * @static
		 */
		addListener: function (el, eType, handler) {
			if (!handler || !handler.call) {
				return false;
			}
			var El = L.getById(el);
			if (El) {
				_wrappedHandler = function (e) {
					var ev = e || window.event;
					return handler.call(ev);
				}
				El['on' + eType] = _wrappedHandler;
			}
		},
		
		/**
		 * @method removeListener
		 * @param {string} el
		 * @param {string} eType
		 */
		removeListener: function (el, eType) {
			var El = L.getById(el);
			if (El) {
				El['on' + eType] = null;
			}
		}
	};
	
	var Style = {
		
		/**
		 * @method hasClass
		 * @param {HTMLElement} el
		 * @param {string} className
		 */
		hasClass: function (el, className) {
			return (new RegExp("(^|\\s)" + className + "(\\s|$)").test(el.className));
		},
		
		/**
		 * @method addClass
		 * @param {HTMLElement} el
		 * @param {string} className
 		 */
		addClass: function (el, className) {
			if (this.hasClass(el, className)) {
        		return;
        	}
        	el.className += " " + className;
		},
		
		/**
		 * @method removeClass
		 * @param {HTMLElement} el
		 * @param {string} className
 		 */
		removeClass: function (el, className) {
	        var classes = el.className.split(/\s+/);
		    for (var i = 0; i < classes.length; i++) {
            	if (classes[i] == className) {
               		delete classes[i];
            	}
        	}
			el.className = classes.join(" ");
		}
	}
	
	return {
		Event: Event,
		Style: Style
	}
	
})();


OOJ.dom = (function () {
	var L = OOJ.lang,
		Style = OOJ.util.Style;

	
	/**
	 * @constructor
	 * @param {HTMLElement} el
	 */
	var Element = function (el) {
		if (!el || typeof el != 'object') {
			return false;
		}
		this._element = el;
	}
	
	Element.prototype = {
		
		/**
		 * @property _eventListeners
		 * @type Array
		 * @private
		 */
		_eventListeners: [],
		
		/**
		 * @method hasClass
		 * @param {string} className
		 */
		hasClass: function (className) {
			return Style.hasClass(this._element, className);
		},
		
		/**
		 * @method addClass
		 * @param {string} className
		 */
		addClass: function (className) {
			Style.addClass(this._element, className);
		},
		
		/**
		 * @method removeClass
		 * @param {Object} className
		 */
		removeClass: function (className) {
			Style.removeClass(this._element, className);
		},
		
		/**
		 * @method getId
		 * @return {string} id
		 */
		getId: function () {
			return this._element.id
		},
		
		/**
		 * @method setId
		 * @param {string} id
		 */
		setId: function (id) {
			this._element.id = id;
		},
		
		/**
		 * @method getDOMElement
		 * @return {DOMElement}
		 */
		getDOMElement: function () {
			return this._element;
		},
		
		/**
		 * @method addEventListener
		 * @param {string} type
		 * @param {Function} handler
		 */
		addEventListener: function (type, handler) {
			if (!handler || !handler.call) {
				return false;
			}
			if (!this._eventListeners[type]) {
				this._eventListeners[type] = [];
			}
			this._eventListeners[type].push(handler);
			var listeners = this._eventListeners[type];
			var wrappedHandler = function (e) {
				var ev = e || window.event;
				for (var i = 0; i < listeners.length; i++) {
					listeners[i].call(ev);
				}
			}
			this._element['on' + type] = wrappedHandler;
		},
		
		/**
		 * @method removeEventListener
		 * @param {string} type
		 * @param {Function} handler
		 */
		removeEventListener: function (type, handler) {
			if (!this._eventListeners[type]) {
				return false;
			}
			if (this._eventListeners[type].length <= 1) {
				delete this._eventListeners[type];
				return true;
				this._element['on' + type] = null;
			}
			var listeners = this._eventListeners[type];
			for (var i = 0; i < listeners.length; i++) {
				if (listeners[i] == handler) {
					listeners.splice(i, 1);
					return true;
				}
			}
			return false;
		}
	}
	
	/**
	 * @method getById
	 * @param {string} id
	 * @return {OOJ.lang.Element}
	 * @static
	 */
	Element.getById = function (id) {
		var element = L.getById(id);
		return new Element(element);
	}
	
	var Button = function (text) {
		var button = document.createElement("input");
		button.setAttribute("type", "button");
		button.setAttribute("value", text);
		Button.superclass.constructor.call(this, button);
		button = null;
	}
	
	L.extend(Button, Element, {
		
		getText: function () {
			return this._element.value;
		},
		
		setText: function (text) {
			this._element.value = text;
		}
		
	});
	
	
	var AButton = function (content) {
		var link = document.createElement("a");
		link.setAttribute("href", "javascript:void(0)");
		if (typeof content == 'string') {
			link.appendChild(document.createTextNode(content));
		} else if (typeof content == 'object') {
			link.appendChild(content);
		}
		AButton.superclass.constructor.call(this, link);
	}
	
	L.extend(AButton, Element);
	
	return {
		Element: Element, 
		Button: Button,
		AButton: AButton
	}
	
})();


